/**
* 版权声明：厦门睿商网络科技有限公司 版权所有 违者必究
* 日    期：2020-02-17
*/
package com.rzico.order.service;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.rzico.account.entity.Payment;
import com.rzico.account.entity.Receivable;
import com.rzico.account.enumx.OrderTypeEnum;
import com.rzico.account.model.Attach;
import com.rzico.account.service.PaymentService;
import com.rzico.account.service.ReceivableService;
import com.rzico.base.CommResult;
import com.rzico.basics.entity.*;
import com.rzico.basics.service.*;
import com.rzico.basics.utils.Kuaidi100;
import com.rzico.base.BaseMapper;
import com.rzico.base.impl.BaseServiceImpl;
import com.rzico.core.entity.SysEmployee;
import com.rzico.core.entity.SysUser;
import com.rzico.core.service.SysEmployeeService;
import com.rzico.core.service.SysSequenceService;
import com.rzico.core.service.SysUserService;
import com.rzico.exception.CustomException;
import com.rzico.order.entity.*;
import com.rzico.order.model.ShippingExportVo;
import com.rzico.order.print.PrinterUtil;
import com.rzico.util.DateUtils;
import com.rzico.util.MD5Utils;
//import com.sun.org.apache.regexp.internal.RE;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import com.rzico.order.mapper.ShippingMapper;
import org.springframework.transaction.annotation.Transactional;
import com.rzico.order.enumx.*;

import java.math.BigDecimal;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * <pre>
 * 送货单业务类
 * </pre>
 *
 * @author Rzico Boot
 * @version 1.0
 */
@Service
@Slf4j
public class ShippingService extends BaseServiceImpl<Shipping, String> {

    @Autowired
    private ShippingMapper shippingMapper;

    @Autowired @Lazy
    private MsgService msgService;

    @Autowired
    private ShippingItemService shippingItemService;

    @Autowired
    private ProductService productService;

    @Autowired
    private FreightService freightService;

    @Autowired
    private ReceiverService receiverService;

    @Autowired
    private BomItemService bomItemService;

    @Autowired
    private EnterpriseService enterpriseService;

    @Autowired
    private ShopService shopService;

    @Autowired
    private MemberService memberService;

    @Autowired
    private CouponService couponService;

    @Autowired
    private CouponCodeService couponCodeService;

    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private SysEmployeeService sysEmployeeService;

    @Autowired
    private OrderLogService orderLogService;

    @Autowired
    private SysSequenceService sysSequenceService;

    @Autowired @Lazy
    private EmptyBarrelService emptyBarrelService;

    @Autowired @Lazy
    private ReceivableService receivableService;

    @Autowired @Lazy
    private OrderPlanService orderPlanService;

    @Autowired @Lazy
    private WarehouseService warehouseService;

    @Autowired @Lazy
    private OrderService orderService;

    @Autowired @Lazy
    private PaymentService paymentService;

    @Autowired @Lazy
    private MapLineService mapLineService;

    @Autowired
    private Kuaidi100 kuaidi100;

    @Autowired @Lazy
    private VirtualProductService virtualProductService;

    @Autowired @Lazy
    private DistributionService distributionService;

    @Autowired @Lazy
    private DistributionItemService distributionItemService;

    @Override
    public BaseMapper<Shipping, String> getMapper() {
        return shippingMapper;
    }

    //物流查询
    public Map<String,Object> deliveryQuery(String trackingNo) {
       List<String> com = kuaidi100.getComInfo(trackingNo);
       if (com==null) {
           return null;
       }
       for (String s:com) {
           Map<String,Object> data = kuaidi100.getExpressInfo(s, trackingNo);
           if (data.containsKey("message") && data.get("message").toString().equals("ok")) {
               return data;
           }
       }
       return null;
    }

    @Transactional(rollbackFor = Exception.class)
    public int insertShipping(Shipping shipping) {
        shipping.setSn(sysSequenceService.generate("order"));
        if (null == shipping.getShippingStatus()){
            shipping.setShippingStatus(0);
        }
        if (null == shipping.getLevel()){
            shipping.setLevel(0);
        }
        if (null == shipping.getShippingFreight()){
            shipping.setShippingFreight(new BigDecimal(0));
        }
        if (null == shipping.getAdminFreight()){
            shipping.setAdminFreight(new BigDecimal(0));
        }
        if (null == shipping.getLevelFreight()){
            shipping.setLevelFreight(new BigDecimal(0));
        }
        shipping.setDeleted(false);
        shipping.setSPrint(0);

        List<ShippingItem> itemsList = new ArrayList<>();
        for (ShippingItem shippingItem : shipping.getItemList()){
            //冗余存储
            shippingItem.setEnterpriseId(shipping.getEnterpriseId());
            itemsList.add(shippingItem);
        }
        shipping.setItemList(itemsList);
        return insertUseGeneratedKeys(shipping);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertUseGeneratedKeys(Shipping shipping) {
        shipping.setSubCost(shipping.calculateSubCost());
        shipping.setSubQuantity(shipping.calculateSubQuantity());
        shipping.setSubPrice(shipping.calculateSubPrice());
        int affectCount = super.insertUseGeneratedKeys(shipping);
        if (affectCount > 0){
            for (ShippingItem shippingItem : shipping.getItemList()){
                shippingItem.setShippingId(shipping.getId());
            }
            shippingItemService.insertUseGeneratedKeyList(shipping.getItemList());
        }
        return affectCount;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteByIds(Object[] ids) {
        int rw = 0;
        for (Object id:ids) {
            Shipping shipping = selectByPrimaryKey(id);
            shipping.setDeleted(true);
            rw = rw + super.updateByPrimaryKeySelective(shipping);
        }
        return rw;
    }

    @Transactional(rollbackFor = Exception.class)
    public int confirm(Long id){
        Shipping shipping = selectByPrimaryKey(id);
        if (null == shipping){
            throw new CustomException("未查找到配送单");
        }
        if (!shipping.getShippingStatus().equals(ShippingStatusEnum.SHIPPING_STATUS_UNCONFIRM.getId())){
            throw new CustomException("订单已派单或已完成");
        }
        shipping.setShippingStatus(ShippingStatusEnum.SHIPPING_STATUS_DISPATCH.getId());
        return super.updateByPrimaryKeySelective(shipping);
    }


    @Transactional(rollbackFor = Exception.class)
    public int dispatch(Long id,Long shopId,String shippingEmployeeId){

        Shipping shipping = selectByPrimaryKey(id);
        if (null == shipping){
            throw new CustomException("未查找到配送单");
        }
        if (shippingEmployeeId==null) {
            shipping.setShippingStatus(ShippingStatusEnum.SHIPPING_STATUS_DISPATCH.getId());
        } else {
            shipping.setShippingStatus(ShippingStatusEnum.SHIPPING_STATUS_SEND.getId());
        }
        shipping.setShopId(shopId);
        shipping.setShippingEmployeeId(shippingEmployeeId);
        super.updateByPrimaryKeySelective(shipping);

        if (shippingEmployeeId!=null) {

            shipping.setItemList(shippingItemService.getItemList(shipping.getId()));
            Map<String, Object> contentSucc = new HashMap<>();
            contentSucc.put("title", "您有新的送货单");
            contentSucc.put("itemList", shipping.getItemList());
            contentSucc.put("sn", shipping.getOrderSn());
            contentSucc.put("id", shipping.getOrderId());
            contentSucc.put("shippingId", shipping.getId());
            SysEmployee sysEmployee = sysEmployeeService.selectByPrimaryKey(shippingEmployeeId);
            if (sysEmployee!=null) {


                if (shipping.getOrderId()!=null) {
                    OrderLog orderLog = new OrderLog();
                    orderLog.setType(OrderLogTypeEnum.ORDER_LOG_TYPE_SHIPPING.getId());
                    orderLog.setContent("订单已派单:" + sysEmployee.getName());
                    orderLog.setCreateDate(new Date());
                    orderLog.setOrderId(shipping.getOrderId());
                    orderLogService.insertUseGeneratedKeys(orderLog);
                }

                SysUser sysUser = sysUserService.selectByPrimaryKey(sysEmployee.getUserId());
                if (sysUser!=null) {
                    msgService.sendNotity(sysUser, "msg-shipping", "您有新的送货单,请尽快处理", JSON.toJSONString(contentSucc),"h1");
                }
            }


        } else {
            shipping.setItemList(shippingItemService.getItemList(shipping.getId()));
            Map<String, Object> contentSucc = new HashMap<>();
            contentSucc.put("title", "您有新的送货单");
            contentSucc.put("itemList", shipping.getItemList());
            contentSucc.put("sn", shipping.getOrderSn());
            contentSucc.put("id", shipping.getOrderId());
            contentSucc.put("shippingId", shipping.getId());

            Shop shop = shopService.selectByPrimaryKey(shopId);
            if (shop!=null) {
                SysEmployee sysEmployee = sysEmployeeService.selectByPrimaryKey(shop.getManagerId());
                if (sysEmployee!=null) {
                    SysUser sysUser = sysUserService.selectByPrimaryKey(sysEmployee.getUserId());
                    if (sysUser!=null) {
                        msgService.sendNotity(sysUser, "msg-shipping", "您有新的送货单,请尽快处理", JSON.toJSONString(contentSucc),"h1");
                    }
                }

                if (shipping.getOrderId()!=null) {
                    OrderLog orderLog = new OrderLog();
                    orderLog.setType(OrderLogTypeEnum.ORDER_LOG_TYPE_SHIPPING.getId());
                    orderLog.setContent("订单转至门店:" + shop.getName());
                    orderLog.setCreateDate(new Date());
                    orderLog.setOrderId(shipping.getOrderId());
                    orderLogService.insertUseGeneratedKeys(orderLog);
                }

            }

        }

        return 1;

    }


    @Transactional(rollbackFor = Exception.class)
    public int reject(Long id) {

        Shipping shipping = selectByPrimaryKey(id);
        if (null == shipping){
            throw new CustomException("未查找到配送单");
        }
        shipping.setShippingStatus(ShippingStatusEnum.SHIPPING_STATUS_DISPATCH.getId());

        shipping.setShippingEmployeeId(null);
        super.updateByPrimaryKeySelective(shipping);

        shipping.setItemList(shippingItemService.getItemList(shipping.getId()));
        Map<String, Object> contentSucc = new HashMap<>();
        contentSucc.put("title", "送货单已驳回");
        contentSucc.put("itemList", shipping.getItemList());
        contentSucc.put("sn", shipping.getOrderSn());
        contentSucc.put("id", shipping.getOrderId());
        contentSucc.put("shippingId", shipping.getId());


        if (shipping.getOrderId()!=null) {
            OrderLog orderLog = new OrderLog();
            orderLog.setType(OrderLogTypeEnum.ORDER_LOG_TYPE_SHIPPING.getId());
            orderLog.setContent("送货单已驳回");
            orderLog.setCreateDate(new Date());
            orderLog.setOrderId(shipping.getOrderId());
            orderLogService.insertUseGeneratedKeys(orderLog);
        }


        Shop shop = shopService.selectByPrimaryKey(shipping.getShopId());
        if (shop!=null) {
            SysEmployee sysEmployee = sysEmployeeService.selectByPrimaryKey(shop.getManagerId());
            if (sysEmployee!=null) {
                SysUser sysUser = sysUserService.selectByPrimaryKey(sysEmployee.getUserId());
                if (sysUser!=null) {
                    msgService.sendNotity(sysUser, "msg-shipping", "送货单已驳回,请尽快处理", JSON.toJSONString(contentSucc),"h6");
                }
            }
        }

        return 1;

    }

    @Transactional(rollbackFor = Exception.class)
    public int cancel(Long id){

        Shipping shipping = selectByPrimaryKey(id);
        if (null == shipping){
            throw new CustomException("未查找到配送单");
        }

        if (!shipping.getShippingStatus().equals(ShippingStatusEnum.SHIPPING_STATUS_UNCONFIRM.getId())
                &&
            !shipping.getShippingStatus().equals(ShippingStatusEnum.SHIPPING_STATUS_DISPATCH.getId())
             &&
            !shipping.getShippingStatus().equals(ShippingStatusEnum.SHIPPING_STATUS_SEND.getId())
           )
        {
               throw new CustomException("送货单不能关闭");

        }

//        if (shipping.getWarehouseId()!=null) {
//            Warehouse warehouse = warehouseService.selectByPrimaryKey(shipping.getWarehouseId());
//            if (warehouse.getStatus().equals(WarehouseStatusEnum.WAREHOUSE_STATUS_COMPLETE.getId())) {
//                throw new CustomException("已出库不能关闭");
//            }
//            if (warehouse.getStatus().equals(WarehouseStatusEnum.WAREHOUSE_STATUS_CONFIRM.getId())) {
//                throw new CustomException("请先作废出库单");
//            }
//        }

        emptyBarrelService.delShipping(shipping);

        if (shipping.getOrderPlanId()!=null) {
            OrderPlan orderPlan = orderPlanService.selectByPrimaryKey(shipping.getOrderPlanId());
            orderPlan.setStatus(0);
            orderPlanService.updateByPrimaryKeySelective(orderPlan);
        }

        shipping.setShippingStatus(ShippingStatusEnum.SHIPPING_STATUS_CANCELED.getId());
        return super.updateByPrimaryKeySelective(shipping);
    }

    @Transactional(rollbackFor = Exception.class)
    public int shipping(Long id,List<ShippingItem> itemList){

        Shipping shipping = selectByPrimaryKey(id);
        if (null == shipping){
            throw new CustomException("未查找到配送单");
        }
        if (!shipping.getShippingStatus().equals(ShippingStatusEnum.SHIPPING_STATUS_DISPATCH.getId()) && !shipping.getShippingStatus().equals(ShippingStatusEnum.SHIPPING_STATUS_SEND.getId())){
            throw new CustomException("订单已发货或已完成");
        }

        List<Long> freights = new ArrayList<>();
        List<String> trackingNos = new ArrayList<>();

        for (ShippingItem shippingItem:itemList) {
            ShippingItem target = shippingItemService.selectByPrimaryKey(shippingItem.getId());
            Product product = productService.findById(target.getProductId());
            if (!freights.contains(product.getFreightId())) {
                freights.add(product.getFreightId());
            }
            if (!trackingNos.contains(shippingItem.getTrackingNo())) {
                trackingNos.add(shippingItem.getTrackingNo());
            }
            target.setTrackingNo(shippingItem.getTrackingNo());
            if (shippingItem.getEmptyBarrelQuantity()==null) {
                shippingItem.setEmptyBarrelQuantity(BigDecimal.ZERO);
            }
            target.setEmptyBarrelQuantity(shippingItem.getEmptyBarrelQuantity());
            int affectCount = shippingItemService.updateByPrimaryKeySelective(target);
            if (affectCount==0) {
                throw new CustomException("无效商品项id");
            }
        }

        //计算运费
        BigDecimal freightFee = BigDecimal.ZERO;
        for (Long freightId:freights) {
            if (freightId!=null && freightId>0L) {
                Freight freight = freightService.findById(freightId);
                for (String trackingNo : trackingNos) {
                    freightFee = freightFee.add(calculateFreight(shipping, freight, trackingNo));
                }
            }
        }

        for (ShippingItem shippingItem:itemList) {
            ShippingItem target = shippingItemService.selectByPrimaryKey(shippingItem.getId());
            target.setShippingFreight(shippingItem.getShippingFreight());
            int affectCount = shippingItemService.updateByPrimaryKeySelective(target);
            if (affectCount==0) {
                throw new CustomException("无效商品项id");
            }
        }

        shipping.setShippingFreight(freightFee);
        shipping.setDeliveryDate(new Date());
        shipping.setShippingStatus(ShippingStatusEnum.SHIPPING_STATUS_RECEIVED.getId());
        Integer w = super.updateByPrimaryKeySelective(shipping);



        //本单未收款
        Map<String, Object> paymentParams = new HashMap<>();
        if (shipping.getOrderId()!=null) {
            paymentParams.put("orderType", 0);
            paymentParams.put("orderId", shipping.getOrderId());
        } else {
            paymentParams.put("orderType", 1);
            paymentParams.put("orderId", shipping.getWarehouseId());
        }

        paymentParams.put("status", 0);
        List<Payment> paymentList = paymentService.selectList(paymentParams);
        for (Payment payment:paymentList) {
            payment.setPaymentDate(new Date());
            payment.setEmployeeId(shipping.getShippingEmployeeId());
            paymentService.updateByPrimaryKeySelective(payment);
        }

        //送达时，登记出桶程回桶
        shipping.setItemList(itemList);
        emptyBarrelService.addShipping(shipping);

        if (shipping.getOrderId()!=null) {
            OrderLog orderLog = new OrderLog();
            orderLog.setType(OrderLogTypeEnum.ORDER_LOG_TYPE_SHIPPING.getId());
            orderLog.setContent("订单已送达");
            orderLog.setCreateDate(new Date());
            orderLog.setOrderId(shipping.getOrderId());
            orderLogService.insertUseGeneratedKeys(orderLog);
        }

        return w;

    }

    @Transactional(rollbackFor = Exception.class)
    public int calculateFreight(Long id,List<ShippingItem> itemList){
        Shipping shipping = selectByPrimaryKey(id);
        if (null == shipping){
            throw new CustomException("未查找到配送单");
        }

        List<Long> freights = new ArrayList<>();
        List<String> trackingNos = new ArrayList<>();

        for (ShippingItem shippingItem:itemList) {
            ShippingItem target = shippingItemService.selectByPrimaryKey(shippingItem.getId());
            Product product = productService.findById(target.getProductId());
            if (!freights.contains(product.getFreightId())) {
                freights.add(product.getFreightId());
            }
            if (!trackingNos.contains(shippingItem.getTrackingNo())) {
                trackingNos.add(shippingItem.getTrackingNo());
            }
            target.setTrackingNo(shippingItem.getTrackingNo());
            int affectCount = shippingItemService.updateByPrimaryKeySelective(target);
            if (affectCount==0) {
                throw new CustomException("无效商品项id");
            }
        }

        //计算运费
        BigDecimal freightFee = BigDecimal.ZERO;
        for (Long freightId:freights) {
            if (freightId!=null && freightId>0L) {
                Freight freight = freightService.findById(freightId);
                for (String trackingNo : trackingNos) {
                    freightFee = freightFee.add(calculateFreight(shipping, freight, trackingNo));
                }
            }
        }

        for (ShippingItem shippingItem:itemList) {
            ShippingItem target = shippingItemService.selectByPrimaryKey(shippingItem.getId());
            target.setShippingFreight(shippingItem.getShippingFreight());
            int affectCount = shippingItemService.updateByPrimaryKeySelective(target);
            if (affectCount==0) {
                throw new CustomException("无效商品项id");
            }
        }

        shipping.setShippingFreight(freightFee);
        shipping.setShippingStatus(ShippingStatusEnum.SHIPPING_STATUS_RECEIVED.getId());
        Integer w = super.updateByPrimaryKeySelective(shipping);

        return w;

    }

    @Transactional(rollbackFor = Exception.class)
    public int updateTrackingNo(Long id,List<ShippingItem> itemList){
        Shipping shipping = selectByPrimaryKey(id);
        if (null == shipping){
            throw new CustomException("未查找到配送单");
        }

        List<Long> freights = new ArrayList<>();
        List<String> trackingNos = new ArrayList<>();

        for (ShippingItem shippingItem:itemList) {
            ShippingItem target = shippingItemService.selectByPrimaryKey(shippingItem.getId());
            Product product = productService.findById(target.getProductId());
            if (!freights.contains(product.getFreightId())) {
                freights.add(product.getFreightId());
            }
            if (!trackingNos.contains(shippingItem.getTrackingNo())) {
                trackingNos.add(shippingItem.getTrackingNo());
            }
            target.setTrackingNo(shippingItem.getTrackingNo());
            int affectCount = shippingItemService.updateByPrimaryKeySelective(target);
            if (affectCount==0) {
                throw new CustomException("无效商品项id");
            }
        }

        //计算运费
        BigDecimal freightFee = BigDecimal.ZERO;
        for (Long freightId:freights) {
            if (freightId!=null && freightId>0L) {
                Freight freight = freightService.findById(freightId);
                for (String trackingNo : trackingNos) {
                    freightFee = freightFee.add(calculateFreight(shipping, freight, trackingNo));
                }
            }
        }

        for (ShippingItem shippingItem:itemList) {
            ShippingItem target = shippingItemService.selectByPrimaryKey(shippingItem.getId());
            target.setShippingFreight(shippingItem.getShippingFreight());
            int affectCount = shippingItemService.updateByPrimaryKeySelective(target);
            if (affectCount==0) {
                throw new CustomException("无效商品项id");
            }
        }

        shipping.setShippingFreight(freightFee);
        Integer w = super.updateByPrimaryKeySelective(shipping);

        return w;

    }

    private Shipping checkShippingContains(List<Shipping> shippings,String sn) {
        Shipping s = null;
        for (Shipping sp:shippings) {
            if (sp.getSn().equals(sn)) {
                s = sp;
                break;
            }
        }
        return s;
    }

    public BigDecimal calculateFreight(Shipping shipping, Freight freight, String trackingNo) {

        BigDecimal quantity = BigDecimal.ZERO;
        BigDecimal weight = BigDecimal.ZERO;
        List<ShippingItem> items = new ArrayList<>();
        for (ShippingItem orderItem:shipping.getItemList()) {
            Product product = productService.findById(orderItem.getProductId());
            if (product.getFreightId()!=null &&  product.getFreightId().equals(freight.getId())) {
                if (trackingNo.equals(orderItem.getTrackingNo())) {
                    weight = weight.add(product.getWeight().multiply(orderItem.getQuantity()));
                    quantity = quantity.add(orderItem.getQuantity());
                    items.add((orderItem));
                }
            }
        }

        BigDecimal fee = freightService.calculate(freight,weight,quantity,shipping.getAreaId());
        BigDecimal bal = fee;

        //金额分摊到每个单品
        if (fee.compareTo(BigDecimal.ZERO)>0) {
            for (ShippingItem shippingItem : items) {
                if (freight.getType().equals(1)) {
                    BigDecimal d = shippingItem.getQuantity().
                            multiply(fee).
                            divide(quantity, 2, BigDecimal.ROUND_DOWN);
                    shippingItem.setShippingFreight(d);
                    bal = bal.subtract(d);

                } else {
                    Product product = productService.findById(shippingItem.getProductId());
                    BigDecimal d = shippingItem.getQuantity().multiply(product.getWeight()).
                            multiply(fee).
                            divide(weight, 2, BigDecimal.ROUND_DOWN);
                    shippingItem.setShippingFreight(d);
                    bal = bal.subtract(d);
                }
            }
            if (bal.compareTo(BigDecimal.ZERO)>0) {
                ShippingItem orderItem = items.get(0);
                orderItem.setShippingFreight(orderItem.getShippingFreight().add(bal));
            }
        }
        return fee;

    }


    @Transactional(rollbackFor = Exception.class)
    public Integer batchShipping(List<ShippingExportVo> shippingExportVos) {

        List<Shipping> shippings = new ArrayList<>();
        Integer errorNum = 0;
        List<ShippingItem> shippingItemList = new ArrayList<>();

        for (ShippingExportVo vo:shippingExportVos) {
            if (vo.getTrackingNo()==null) {
                vo.setErrMsg("物流单号不能为空");
                errorNum ++;
                break;
            }
            ShippingItem shippingItem = shippingItemService.selectByPrimaryKey(vo.getId());
            if (shippingItem==null) {
                vo.setErrMsg("无效发货ID号");
                errorNum++;
            } else {
                shippingItem.setTrackingNo(vo.getTrackingNo());
                shippingItemList.add(shippingItem);
            }
            Shipping shipping = checkShippingContains(shippings,vo.getSn());
            if (shipping==null) {
                Map<String,Object> prms = new HashMap<>();
                prms.put("sn",vo.getSn());
                List<Shipping> spps = shippingMapper.selectList(prms);
                if (spps.size()>0) {
                    shipping = spps.get(0);
                    shippings.add(shipping);
                }
            }
            if (shipping==null) {
                vo.setErrMsg("无效发货单号");
                errorNum++;
            }
        }
        if (errorNum==0) {
            for (ShippingItem shippingItem:shippingItemList) {
                shippingItemService.updateByPrimaryKeySelective(shippingItem);
            }
            //没有错误开始保存
            for (Shipping shipping:shippings) {
                Integer num = 0;
                shipping.setItemList(shippingItemService.getItemList(shipping.getId()));
                for (ShippingItem shippingItem:shipping.getItemList()) {
                    if (shippingItem.getTrackingNo() !=null) {
                        num ++;
                    }
                }
                if (num == shipping.getItemList().size()) {

                        if (shipping.getShippingStatus().equals(ShippingStatusEnum.SHIPPING_STATUS_DISPATCH.getId()) || shipping.getShippingStatus().equals(ShippingStatusEnum.SHIPPING_STATUS_SEND.getId())) {
                            shipping(shipping.getId(), shipping.getItemList());
                        } else {
                            updateTrackingNo(shipping.getId(), shipping.getItemList());
                        }

                }
            }
        }
        return errorNum;

    }


    @Transactional(rollbackFor = Exception.class)
    public int completeBatch(List<Shipping> shippingList) {
        for (Shipping shipping:shippingList) {
            complete(shipping.getId(),null);
        }
        return shippingList.size();

    }

    @Transactional(rollbackFor = Exception.class)
    public int complete(Long id,List<ShippingItem> itemList) {

        Shipping shipping = selectByPrimaryKey(id);
        if (null == shipping){
            throw new CustomException("未查找到配送单");
        }

        shipping.setShippingStatus(ShippingStatusEnum.SHIPPING_STATUS_COMPLETE.getId());
        shipping.setCompleteDate(new Date());

        if (itemList!=null && itemList.size()>0) {


            for (ShippingItem shippingItem : itemList) {
                ShippingItem target = shippingItemService.selectByPrimaryKey(shippingItem.getId());
                if (shippingItem.getEmptyBarrelQuantity()==null) {
                    shippingItem.setEmptyBarrelQuantity(target.getEmptyBarrelQuantity());
                }
                target.setEmptyBarrelQuantity(shippingItem.getEmptyBarrelQuantity());
                int affectCount = shippingItemService.updateByPrimaryKeySelective(target);
                if (affectCount==0) {
                    throw new CustomException("无效商品项id");
                }

                Map<String,Object> params = new HashMap<>();
                params.put("shipping_item_id",shippingItem.getId());
                List<EmptyBarrel> emptyBarrelList = emptyBarrelService.selectList(params);
                for (EmptyBarrel emptyBarrel:emptyBarrelList) {
                    emptyBarrel.setQuantity(shippingItem.getEmptyBarrelQuantity());
                    emptyBarrel.setAudited(1);
                    emptyBarrelService.updateByPrimaryKeySelective(emptyBarrel);
                }

            }
        }

        Map<String,Object> params = new HashMap<>();
        params.put("shipping_id",shipping.getId());
        params.put("audited",0);
        List<EmptyBarrel> emptyBarrelList = emptyBarrelService.selectList(params);
        for (EmptyBarrel emptyBarrel:emptyBarrelList) {
            emptyBarrel.setAudited(1);
            emptyBarrelService.updateByPrimaryKeySelective(emptyBarrel);
        }

        int affectCount = super.updateByPrimaryKeySelective(shipping);


        Shop shop = shopService.selectByPrimaryKey(shipping.getShopId());
        if (shop.getMemberId()!=null) {
            Member shippingMember = memberService.findById(shop.getMemberId());
            //送货时自动生在提货券
            shipping.setItemList(shippingItemService.getItemList(shipping.getId()));
            for (ShippingItem shippingItem:shipping.getItemList()) {
                Product product = productService.selectByPrimaryKey(shippingItem.getProductId());
                if (product.getDistributionId() != null) {
                    Distribution distribution = distributionService.findById(product.getDistributionId());
                    distribution.setItemList(distributionItemService.getItemList(distribution.getId()));
                    if (distribution!=null && distribution.getVWarehouseCoupon(shippingMember.vipObject())) {
                        Coupon coupon = couponService.create(product);
                        couponCodeService.createAndInc(coupon,shippingMember.getId(),shipping.getSn()+"T",shippingItem.getQuantity().intValue());
                    }
                }
            }

        }

        //压桶及退款时，生成对应的应付款
        Map<String, Object> virtualParams = new HashMap<>();
        virtualParams.clear();
        virtualParams.put("shippingId", shipping.getId());
        virtualParams.put("sortField", "id");
        virtualParams.put("sortType", "desc");
        List<VirtualProduct> virtualProductList = virtualProductService.selectList(virtualParams);

        BigDecimal virtualAmount = BigDecimal.ZERO;
        for (VirtualProduct virtualProduct:virtualProductList) {
            virtualAmount = virtualAmount.add(virtualProduct.getPrice());
        }

        if (virtualAmount.compareTo(BigDecimal.ZERO)>0) {

            Receivable virtualReceivable = new Receivable();
            virtualReceivable.setAmount(virtualAmount);
            virtualReceivable.setAmountPaid(BigDecimal.ZERO);
            virtualReceivable.setQuantityPaid(0);
            virtualReceivable.setQuantity(0);
            virtualReceivable.setType(1);
            //订单未付款
            virtualReceivable.setStatus(0);
            virtualReceivable.setPaymentPluginId("cashPayPlugin");
            virtualReceivable.setPaymentPluginName("现金");
            virtualReceivable.setDeleted(false);
            virtualReceivable.setMemberId(shipping.getMemberId());
            virtualReceivable.setEnterpriseId(shipping.getEnterpriseId());
            if (shipping.getOrderId() != null) {
                virtualReceivable.setOrderId(shipping.getOrderId());
                virtualReceivable.setOrderSn(shipping.getOrderSn());
                virtualReceivable.setOrderType(0);
            } else {
                Warehouse warehouse = warehouseService.selectByPrimaryKey(shipping.getWarehouseId());
                virtualReceivable.setOrderId(shipping.getWarehouseId());
                virtualReceivable.setOrderSn(warehouse.getSn());
                virtualReceivable.setOrderType(1);
            }
            receivableService.insertUseGeneratedKeys(virtualReceivable);

        }

        //本单所有收款单
        Map<String, Object> paymentParams = new HashMap<>();
        if (shipping.getOrderId()!=null) {
            paymentParams.put("orderType", 0);
            paymentParams.put("orderId", shipping.getOrderId());
        } else {
            paymentParams.put("orderType", 1);
            paymentParams.put("orderId", shipping.getWarehouseId());
        }

        paymentParams.put("status", 0);
        List<Payment> paymentList = paymentService.selectList(paymentParams);

        //本单所有应收款
        params.clear();
        if (shipping.getOrderId()!=null) {
            params.put("orderType", 0);
            params.put("orderId", shipping.getOrderId());
        } else {
            params.put("orderType", 1);
            params.put("orderId", shipping.getWarehouseId());
        }
        params.put("sortField","id");
        params.put("sortType","asc");
        params.put("status", 0);
        List<Receivable> receivableList = receivableService.selectList(params);

        BigDecimal amountPaid = BigDecimal.ZERO;
        BigDecimal quantityPaid = BigDecimal.ZERO;
        BigDecimal price = BigDecimal.ZERO;

        Integer num = 0;
        for (Payment payment:paymentList) {
            if (!"debtPayPlugin".equals(payment.getPaymentPluginId())) {
                if (payment.getQuantity()==null) {
                    payment.setQuantity(BigDecimal.ZERO);
                }
                quantityPaid = quantityPaid.add(payment.getQuantity());
                amountPaid = amountPaid.add(payment.getAmount());
                payment.setStatus(Payment.STATUS_SUCCESS);
                if (payment.getPaymentDate()==null) {
                    payment.setPaymentDate(new Date());
                }
                payment.setEmployeeId(shipping.getShippingEmployeeId());
                paymentService.updateByPrimaryKeySelective(payment);
            } else {
                paymentService.deleteByPrimaryKey(payment.getId());
            }
        }

        //先冲本单
        for (Receivable receivable : receivableList) {
            if (receivable.getAvailableAmount().compareTo(BigDecimal.ZERO)>0) {
                BigDecimal amount = BigDecimal.ZERO;
                if (receivable.getAvailableAmount().compareTo(amountPaid) >= 0) {
                    amount = amountPaid;
                } else {
                    amount = receivable.getAvailableAmount();
                }
                price = receivable.calcPaperPrice();
                BigDecimal quantity = BigDecimal.ZERO;
                if (price.compareTo(BigDecimal.ZERO)!=0) {
                    quantity = amount.divide(price,0,BigDecimal.ROUND_HALF_DOWN);
                }
                receivable.setQuantityPaid(receivable.getQuantityPaid()+quantity.intValue());
                receivable.setAmountPaid(receivable.getAmountPaid().add(amount));
                if (receivable.getAvailableAmount().compareTo(BigDecimal.ZERO) <= 0) {
                    receivable.setStatus(2);
                } else {
                    receivable.setStatus(1);
                }
                receivableService.updateByPrimaryKeySelective(receivable);

                amountPaid = amountPaid.subtract(amount);
                quantityPaid = quantityPaid.subtract(quantity);
            }
        }

        //冲欠款欠款
        if (amountPaid.compareTo(BigDecimal.ZERO)>0) {
            Map<String, Object> hisParams = new HashMap<String, Object>();
            hisParams.put("memberId", shipping.getMemberId());
            hisParams.put("status", 0);
            hisParams.put("enterpriseId", shipping.getEnterpriseId());
            hisParams.put("sortField", "id");
            hisParams.put("sortType", "asc");
            List<Receivable> historyReceivableList = receivableService.selectList(hisParams);
            for (Receivable receivable : historyReceivableList) {
                if (receivable.getAvailableAmount().compareTo(BigDecimal.ZERO)>0) {
                    BigDecimal amount = BigDecimal.ZERO;
                    if (receivable.getAvailableAmount().compareTo(amountPaid) >= 0) {
                        amount = amountPaid;
                    } else {
                        amount = receivable.getAvailableAmount();
                    }
                    price = receivable.calcPaperPrice();
                    BigDecimal quantity = BigDecimal.ZERO;
                    if (price.compareTo(BigDecimal.ZERO)!=0) {
                        quantity = amount.divide(price,0,BigDecimal.ROUND_HALF_DOWN);
                    }
                    receivable.setQuantityPaid(receivable.getQuantityPaid()+quantity.intValue());
                    receivable.setAmountPaid(receivable.getAmountPaid().add(amount));
                    if (receivable.getAvailableAmount().compareTo(BigDecimal.ZERO) <= 0) {
                        receivable.setStatus(2);
                    } else {
                        receivable.setStatus(1);
                    }
                    receivableService.updateByPrimaryKeySelective(receivable);

                    amountPaid = amountPaid.subtract(amount);
                    quantityPaid = quantityPaid.subtract(quantity);
                }
            }
        }


        if (amountPaid.compareTo(BigDecimal.ZERO)!=0) {
            throw new CustomException("冲账不平,不能核销");
        }

        if (shipping.getOrderId()!=null) {
            OrderLog orderLog = new OrderLog();
            orderLog.setType(OrderLogTypeEnum.ORDER_LOG_TYPE_SHIPPING.getId());
            orderLog.setContent("订单已核销");
            orderLog.setCreateDate(new Date());
            orderLog.setOrderId(shipping.getOrderId());
            orderLogService.insertUseGeneratedKeys(orderLog);
        }

        return affectCount;
    }


    public List<ShippingExportVo> selectShippingExport(Map<String, Object> params) {
        return shippingMapper.selectShippingExport(params);
    }

    /**
     * 生成出入库
     * @param orderPlan
     */
    @Transactional(rollbackFor = Exception.class)
    public Warehouse insertWarehouse(OrderPlan orderPlan,Order order, Shop shop, String sn) {

        Warehouse warehouse = new Warehouse();
        warehouse.setSn(sn);
        warehouse.setOrderPlanId(orderPlan.getId());
        warehouse.setAddress(order.getAddress());
        warehouse.setAreaId(order.getAreaId());
        warehouse.setAreaName(order.getAreaName());
        warehouse.setConsignee(order.getConsignee());
        warehouse.setPhone(order.getPhone());
        warehouse.setMemo(order.getMemo());
        warehouse.setStatus(0);
        warehouse.setOrderMethod(order.getOrderMethod());
        warehouse.setShippingMethod(order.getShippingMethod());
        warehouse.setWarehouseType(WarehouseTypeEnum.WAREHOUSE_TYPE_SALE_OUT.getId());
        warehouse.setSubPrice(BigDecimal.ZERO);
        warehouse.setSubQuantity(BigDecimal.ZERO);
        warehouse.setTaxType(order.getTaxType());
        warehouse.setMemberId(order.getMemberId());

        warehouse.setOrderId(order.getId());
        warehouse.setOrderSn(order.getSn());

        warehouse.setMemo(orderPlan.getName()+"(第"+String.valueOf(orderPlan.getSeqno())+"次)");

        warehouse.setEnterpriseId(order.getEnterpriseId());
        warehouse.setShopId(shop.getId());
        warehouse.setDeleted(false);
        warehouse.setOfficeId(order.getOfficeId());
        warehouse.setSPrint(0);
        warehouse.setSupplierId(order.getMemberId());
        warehouse.setOrderDate(orderPlan.getPlanDate());
        warehouse.setCompanyId(order.getCompanyId());

        List<BomItem> bomItemList = bomItemService.getItemList(orderPlan.getBomId(),String.valueOf(orderPlan.getSeqno()));

        if (bomItemList.size()==0) {
            throw  new CustomException("无法获取套餐设置");
        }
        //明细表数据
        List<WarehouseItem> itemsList = new ArrayList<>();
        for (BomItem orderItem : bomItemList){
            Product product = productService.selectByPrimaryKey(orderItem.getProductId());

                WarehouseItem warehouseItem = new WarehouseItem();
                warehouseItem.setSubType(product.getSubType());
                warehouseItem.setCost(product.getCost());
                warehouseItem.setName(product.getName());
                warehouseItem.setPrice(BigDecimal.ZERO);
                warehouseItem.setQuantity(orderItem.getConvRate());
                warehouseItem.setSn(product.getSn());
                warehouseItem.setUnit(product.getUnit());
                warehouseItem.setSpec(product.getSpec());
                warehouseItem.setThumbnail(product.getThumbnail());
                warehouseItem.setProductId(product.getId());
                warehouseItem.setWarehouseId(warehouse.getId());
                warehouseItem.setDiscount(BigDecimal.ZERO);
                //冗余存储
                warehouseItem.setShopId(warehouse.getShopId());
                warehouseItem.setEnterpriseId(warehouse.getEnterpriseId());
                warehouseItem.setTax(BigDecimal.ZERO);
                itemsList.add(warehouseItem);

        }
        warehouse.setItemList(itemsList);

        warehouse.setSubPrice(warehouse.calculateSubPrice());
        warehouse.setSubQuantity(warehouse.calculateSubQuantity());

        if (itemsList.size()>0) {

            warehouseService.insertUseGeneratedKeys(warehouse);
            //自动确认
            warehouseService.confirm(warehouse.getId());
        }

        return warehouse;

    }

    @Transactional(rollbackFor = Exception.class)
    public List<Shipping> orderPlanImport(Long enterpriseId,Date shippingDate,String sn) {

        Enterprise enterprise = enterpriseService.selectByPrimaryKey(enterpriseId);

        Map<String,Object> params = new HashMap<>();
        //检查是否存在待配送订单
        params.put("status", 0);
        params.put("enterpriseId", enterpriseId);
        params.put("planDate", org.apache.commons.lang3.time.DateUtils.truncate(shippingDate,Calendar.DATE));
        List<OrderPlan> orderPlanList = orderPlanService.selectList(params);
        Integer w = 0;
        for (OrderPlan orderPlan:orderPlanList) {

            Order order = orderService.selectByPrimaryKey(orderPlan.getOrderId());

            Receiver receiver = receiverService.selectByPrimaryKey(order.getReceiverId());

            Double lat = 0d;
            Double lng = 0d;

            MapLine mapLine = null;
            if (receiver!=null)  {
                lat = receiver.getLat();
                lng = receiver.getLng();
                mapLine = mapLineService.findByPoint(enterprise,null,lat,lng);
            }

            Shop shop = null;
            if (mapLine!=null) {
                shop = shopService.findById(mapLine.getShopId());
            } else {
                //没有围拦的分配给总店
                shop = shopService.findByPoint(enterprise,lat,lng);
            }

            if (shop==null) {
                throw new CustomException(order.getAddress()+"不在配送范围");
            }

            w ++ ;
            insertWarehouse(orderPlan,order,shop,sn+"s"+String.valueOf(w));
            orderPlan.setStatus(1);
            orderPlanService.updateByPrimaryKeySelective(orderPlan);

        }

        params.clear();
        params.put("enterpriseId", enterpriseId);
        params.put("snlike", sn+"s");
        return shippingMapper.selectList(params);

    }


    public void print(Long shippingId) {

        Shipping shipping = shippingMapper.selectByPrimaryKey(shippingId);
        shipping.setItemList(shippingItemService.getItemList(shippingId));

        Shop shop = shopService.selectByPrimaryKey(shipping.getShopId());
        if (shop == null) {
            return;
        }

        if (shop.getPrinterp() != null && shop.getPrinteru() != null) {

            Enterprise enterprise = enterpriseService.selectByPrimaryKey(shipping.getEnterpriseId());
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String data =
                    "<MS>6</MS><N>1</N><S2><C>" + "送货单" + "</C></S2>" +
                            "<C>" + enterprise.getName() + "</C>";

            data = data +
                    "................................" +
                    "时间:" + sdf.format(shipping.getCreateDate()) + "<RN>" +
                    "订单号:" + shipping.getOrderSn() + "<RN>" +
                    "配送站:" + shop.getName() + "<RN>" +
                    "收货人:" + shipping.getConsignee() + "<RN>" +
                    "电话:" + shipping.getPhone() + "<RN>" +
                    "地址:" + shipping.getAddress() + "<RN>";
            if (shipping.getHopeDate() != null) {
                SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
                data = data + "预约:" + sf.format(shipping.getHopeDate()) + "<RN>";
            }
            data = data + "<RN>商品名称            数量    金额<RN>";
            data = data + "................................";
            for (ShippingItem shippingItem : shipping.getItemList()) {
                String name = shippingItem.getName();
                data = data + "<TR><TD>" + name + "</TD><TD>" + String.valueOf(shippingItem.getQuantity()) + "</TD><TD>" + String.valueOf(shippingItem.getSubTotal()) + "</TD></TR><RN>";
            }
            data = data + "................................";

//            if (order.getPaymentPluginId() != null && order.getPaymentPluginId().equals("timePayPlugin")) {
//                data = data + "月卡：".concat(order.getCouponCode().getCoupon().getName()).concat("(余数:" + String.valueOf(order.getCouponCode().getStock()) + "次)") + "<RN>";
//            }

            Order order = orderService.selectByPrimaryKey(shipping.getOrderId());

            if (shipping.getMemo() != null) {
                data = data + "备注：".concat(shipping.getMemo()) + "<RN>";
            }
            if (order.getMemo() != null) {
                data = data + "留言：".concat(order.getMemo()) + "<RN>";
            }
            if (enterprise.getPhone() != null) {
                data = data + "客服：".concat(enterprise.getPhone()) + "<RN>";
            }
            String url = enterprise.getDomain() + "/q/818806" + order.getSn() + ".jhtml";
            //String iso = new String(url.getBytes("UTF-8"), "ISO-8859-1");
            data = data + "<RN><RN><QR>" + url + "</QR>";

            PrinterUtil.print(shop.getPrinteru(), shop.getPrinterp(),data);

        }
    }


}
